package com.yunke.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yunke.common.exception.YunkeException;
import com.yunke.common.result.YunkeResultCode;
import com.yunke.common.security.YunkeSecurityUtil;
import com.yunke.common.util.YunkeIdUtils;
import com.yunke.dto.YunkeCreateRechargeDto;
import com.yunke.dto.YunkeWithdrawalDto;
import com.yunke.entity.*;
import com.yunke.mapper.*;
import com.yunke.service.YunkePayService;
import com.yunke.service.YunkeSmsService;
import com.yunke.vo.YunkeBalanceVo;
import com.yunke.vo.YunkeRechargeConfigVo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;

import java.math.BigDecimal;
import java.util.*;

/**
 * 支付系统Service实现类
 * 
 * @author yunke
 * @since 1.0.0
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class YunkePayServiceImpl implements YunkePayService {

    private final YunkeRechargeOrderMapper rechargeOrderMapper;
    private final YunkeWithdrawalMapper withdrawalMapper;
    private final YunkeAmountLogMapper amountLogMapper;
    private final YunkeUserMapper userMapper;
    private final YunkeSmsService smsService;

    @Override
    public YunkeRechargeConfigVo getRechargeConfig() {
        YunkeRechargeConfigVo config = new YunkeRechargeConfigVo();
        
        // 设置充值金额范围
        config.setMinAmount(new BigDecimal("1.00"));
        config.setMaxAmount(new BigDecimal("50000.00"));
        
        // 设置推荐充值金额
        List<BigDecimal> recommendAmounts = Arrays.asList(
            new BigDecimal("10.00"),
            new BigDecimal("50.00"),
            new BigDecimal("100.00"),
            new BigDecimal("500.00"),
            new BigDecimal("1000.00"),
            new BigDecimal("5000.00")
        );
        config.setRecommendAmounts(recommendAmounts);
        
        // 设置支付方式
        List<YunkeRechargeConfigVo.PayTypeVo> payTypes = new ArrayList<>();
        
        YunkeRechargeConfigVo.PayTypeVo wechat = new YunkeRechargeConfigVo.PayTypeVo();
        wechat.setType(1);
        wechat.setName("微信支付");
        wechat.setEnabled(true);
        wechat.setFeeRate(new BigDecimal("0.006"));
        wechat.setIcon("wechat-pay.png");
        payTypes.add(wechat);
        
        YunkeRechargeConfigVo.PayTypeVo alipay = new YunkeRechargeConfigVo.PayTypeVo();
        alipay.setType(2);
        alipay.setName("支付宝");
        alipay.setEnabled(true);
        alipay.setFeeRate(new BigDecimal("0.006"));
        alipay.setIcon("alipay.png");
        payTypes.add(alipay);
        
        config.setPayTypes(payTypes);
        config.setDescription("充值说明：1. 充值金额实时到账；2. 支持微信、支付宝支付；3. 如有疑问请联系客服。");
        
        return config;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public YunkeRechargeOrder createRechargeOrder(YunkeCreateRechargeDto dto) {
        // 获取当前用户ID
        Long userId = YunkeSecurityUtil.getCurrentUserId();
        
        // 验证充值金额
        if (dto.getAmount().compareTo(new BigDecimal("1.00")) < 0) {
            throw new YunkeException(YunkeResultCode.PARAM_ERROR, "充值金额不能少于1元");
        }
        if (dto.getAmount().compareTo(new BigDecimal("50000.00")) > 0) {
            throw new YunkeException(YunkeResultCode.PARAM_ERROR, "单次充值金额不能超过50000元");
        }
        
        // 创建充值订单
        YunkeRechargeOrder order = new YunkeRechargeOrder();
        order.setUserId(userId);
        order.setOrderNo(generateOrderNo());
        order.setAmount(dto.getAmount());
        order.setPayAmount(dto.getAmount()); // 实付金额等于充值金额
        order.setPayType(dto.getPayType());
        order.setPayStatus(0); // 待支付
        order.setClientIp(dto.getClientIp());
        order.setExpireTime(System.currentTimeMillis() + 30 * 60 * 1000); // 30分钟过期
        
        rechargeOrderMapper.insert(order);
        
        log.info("创建充值订单成功: userId={}, orderNo={}, amount={}", userId, order.getOrderNo(), dto.getAmount());
        return order;
    }

    @Override
    public Map<String, Object> getRechargeStatus(String orderNo) {
        YunkeRechargeOrder order = rechargeOrderMapper.selectOne(
            new LambdaQueryWrapper<YunkeRechargeOrder>()
                .eq(YunkeRechargeOrder::getOrderNo, orderNo)
        );
        
        if (order == null) {
            throw new YunkeException(YunkeResultCode.DATA_NOT_FOUND, "订单不存在");
        }
        
        Map<String, Object> result = new HashMap<>();
        result.put("orderNo", order.getOrderNo());
        result.put("amount", order.getAmount());
        result.put("payAmount", order.getPayAmount());
        result.put("payStatus", order.getPayStatus());
        result.put("payTime", order.getPayTime());
        result.put("expireTime", order.getExpireTime());
        
        // 支付状态文本
        String statusText;
        switch (order.getPayStatus()) {
            case 0: statusText = "待支付"; break;
            case 1: statusText = "支付成功"; break;
            case 2: statusText = "支付失败"; break;
            case 3: statusText = "已取消"; break;
            default: statusText = "未知状态"; break;
        }
        result.put("payStatusText", statusText);
        
        return result;
    }

    @Override
    public YunkeBalanceVo getUserBalance(Long userId) {
        YunkeUser user = userMapper.selectById(userId);
        if (user == null) {
            throw new YunkeException(YunkeResultCode.USER_NOT_EXIST);
        }
        
        YunkeBalanceVo balanceVo = new YunkeBalanceVo();
        balanceVo.setUserId(userId);
        balanceVo.setBalance(user.getBalance() != null ? user.getBalance() : BigDecimal.ZERO);
        balanceVo.setTotalIncome(user.getTotalIncome() != null ? user.getTotalIncome() : BigDecimal.ZERO);
        balanceVo.setDaziIncome(user.getDaziIncome() != null ? user.getDaziIncome() : BigDecimal.ZERO);
        balanceVo.setServiceIncome(user.getServiceIncome() != null ? user.getServiceIncome() : BigDecimal.ZERO);
        balanceVo.setCommunityIncome(user.getCommunityIncome() != null ? user.getCommunityIncome() : BigDecimal.ZERO);
        balanceVo.setFirstCommissionIncome(user.getFirstCommissionIncome() != null ? user.getFirstCommissionIncome() : BigDecimal.ZERO);
        balanceVo.setSecondCommissionIncome(user.getSecondCommissionIncome() != null ? user.getSecondCommissionIncome() : BigDecimal.ZERO);
        balanceVo.setVipIncome(user.getVipIncome() != null ? user.getVipIncome() : BigDecimal.ZERO);
        balanceVo.setWithdrawnAmount(user.getWithdrawnAmount() != null ? user.getWithdrawnAmount() : BigDecimal.ZERO);
        
        // 计算冻结金额（待审核的提现金额）
        BigDecimal frozenAmount = calculateFrozenAmount(userId);
        balanceVo.setFrozenAmount(frozenAmount);
        
        // 计算可提现金额
        BigDecimal availableWithdrawal = balanceVo.getBalance().subtract(frozenAmount);
        balanceVo.setAvailableWithdrawal(availableWithdrawal.compareTo(BigDecimal.ZERO) > 0 ? availableWithdrawal : BigDecimal.ZERO);
        
        // TODO: 检查是否设置了支付密码
        balanceVo.setHasPayPassword(false);
        
        return balanceVo;
    }

    @Override
    public IPage<YunkeAmountLog> getAmountLog(Long userId, Integer type, Integer pageNum, Integer pageSize) {
        Page<YunkeAmountLog> page = new Page<>(pageNum, pageSize);
        
        LambdaQueryWrapper<YunkeAmountLog> queryWrapper = new LambdaQueryWrapper<YunkeAmountLog>()
            .eq(YunkeAmountLog::getUserId, userId)
            .orderByDesc(YunkeAmountLog::getCreateTime);
        
        if (type != null) {
            queryWrapper.eq(YunkeAmountLog::getType, type);
        }
        
        return amountLogMapper.selectPage(page, queryWrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public YunkeWithdrawal applyWithdrawal(YunkeWithdrawalDto dto) {
        Long userId = YunkeSecurityUtil.getCurrentUserId();
        
        // 验证提现金额
        if (dto.getAmount().compareTo(new BigDecimal("1.00")) < 0) {
            throw new YunkeException(YunkeResultCode.PARAM_ERROR, "提现金额不能少于1元");
        }
        if (dto.getAmount().compareTo(new BigDecimal("10000.00")) > 0) {
            throw new YunkeException(YunkeResultCode.PARAM_ERROR, "单次提现金额不能超过10000元");
        }
        
        // 验证用户余额
        YunkeUser user = userMapper.selectById(userId);
        if (user == null) {
            throw new YunkeException(YunkeResultCode.USER_NOT_EXIST);
        }
        
        BigDecimal balance = user.getBalance() != null ? user.getBalance() : BigDecimal.ZERO;
        BigDecimal frozenAmount = calculateFrozenAmount(userId);
        BigDecimal availableBalance = balance.subtract(frozenAmount);
        
        if (availableBalance.compareTo(dto.getAmount()) < 0) {
            throw new YunkeException(YunkeResultCode.PARAM_ERROR, "余额不足");
        }
        
        // TODO: 验证支付密码
        // verifyPayPassword(userId, dto.getPayPassword());
        
        // 计算手续费（按照1%计算）
        BigDecimal feeRate = new BigDecimal("0.01");
        BigDecimal fee = dto.getAmount().multiply(feeRate);
        BigDecimal arrivalAmount = dto.getAmount().subtract(fee);
        
        // 创建提现申请
        YunkeWithdrawal withdrawal = new YunkeWithdrawal();
        withdrawal.setUserId(userId);
        withdrawal.setWithdrawalNo(generateWithdrawalNo());
        withdrawal.setAmount(dto.getAmount());
        withdrawal.setFee(fee);
        withdrawal.setArrivalAmount(arrivalAmount);
        withdrawal.setWithdrawalType(dto.getWithdrawalType());
        withdrawal.setAccount(dto.getAccount());
        withdrawal.setAccountName(dto.getAccountName());
        withdrawal.setBankName(dto.getBankName());
        withdrawal.setBankCard(dto.getBankCard());
        withdrawal.setAuditStatus(0); // 待审核
        withdrawal.setPayStatus(0); // 未打款
        
        withdrawalMapper.insert(withdrawal);
        
        log.info("创建提现申请成功: userId={}, withdrawalNo={}, amount={}", userId, withdrawal.getWithdrawalNo(), dto.getAmount());
        return withdrawal;
    }

    @Override
    public IPage<YunkeWithdrawal> getWithdrawalList(Long userId, Integer pageNum, Integer pageSize) {
        Page<YunkeWithdrawal> page = new Page<>(pageNum, pageSize);
        
        LambdaQueryWrapper<YunkeWithdrawal> queryWrapper = new LambdaQueryWrapper<YunkeWithdrawal>()
            .eq(YunkeWithdrawal::getUserId, userId)
            .orderByDesc(YunkeWithdrawal::getCreateTime);
        
        return withdrawalMapper.selectPage(page, queryWrapper);
    }

    @Override
    public boolean setPayPassword(Long userId, String payPassword, String smsCode) {
        // TODO: 验证短信验证码
        
        // TODO: 加密并保存支付密码
        
        log.info("设置支付密码成功: userId={}", userId);
        return true;
    }

    @Override
    public boolean changePayPassword(Long userId, String oldPayPassword, String newPayPassword) {
        // TODO: 验证旧支付密码
        
        // TODO: 加密并保存新支付密码
        
        log.info("修改支付密码成功: userId={}", userId);
        return true;
    }

    @Override
    public Map<String, Object> getPaymentStatistics(Long userId, Long startTime, Long endTime) {
        // TODO: 实现收支统计逻辑
        Map<String, Object> statistics = new HashMap<>();
        statistics.put("totalIncome", BigDecimal.ZERO);
        statistics.put("totalExpense", BigDecimal.ZERO);
        statistics.put("rechargeAmount", BigDecimal.ZERO);
        statistics.put("withdrawalAmount", BigDecimal.ZERO);
        
        return statistics;
    }

    @Override
    public String handleWechatCallback(String notifyData) {
        // TODO: 实现微信支付回调处理
        log.info("处理微信支付回调: {}", notifyData);
        return "SUCCESS";
    }

    @Override
    public String handleAlipayCallback(Map<String, String> notifyData) {
        // TODO: 实现支付宝回调处理
        log.info("处理支付宝回调: {}", notifyData);
        return "SUCCESS";
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean balancePay(Long userId, BigDecimal amount, String orderNo, String payPassword, 
                             String title, String description) {
        // 验证支付密码
        if (!verifyPayPassword(userId, payPassword)) {
            throw new YunkeException(YunkeResultCode.PARAM_ERROR, "支付密码错误");
        }
        
        // 扣减用户余额
        boolean result = deductUserBalance(userId, amount, 3, orderNo, title, description);
        
        log.info("余额支付完成: userId={}, amount={}, orderNo={}, result={}", userId, amount, orderNo, result);
        return result;
    }

    @Override
    public boolean verifyPayPassword(Long userId, String payPassword) {
        // TODO: 实现支付密码验证
        // 这里简单返回true，实际应该从数据库查询并验证加密后的支付密码
        log.info("验证支付密码: userId={}", userId);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean addUserBalance(Long userId, BigDecimal amount, Integer type, String orderNo, 
                                 String title, String description) {
        // 查询用户当前余额
        YunkeUser user = userMapper.selectById(userId);
        if (user == null) {
            throw new YunkeException(YunkeResultCode.USER_NOT_EXIST);
        }
        
        BigDecimal beforeBalance = user.getBalance() != null ? user.getBalance() : BigDecimal.ZERO;
        BigDecimal afterBalance = beforeBalance.add(amount);
        
        // 更新用户余额
        user.setBalance(afterBalance);
        userMapper.updateById(user);
        
        // 记录资金流水
        YunkeAmountLog amountLog = new YunkeAmountLog();
        amountLog.setUserId(userId);
        amountLog.setOrderNo(orderNo);
        amountLog.setType(type);
        amountLog.setAmount(amount);
        amountLog.setBeforeBalance(beforeBalance);
        amountLog.setAfterBalance(afterBalance);
        amountLog.setTitle(title);
        amountLog.setDescription(description);
        amountLog.setOperatorId(userId);
        amountLog.setOperatorType(1); // 用户操作
        
        amountLogMapper.insert(amountLog);
        
        log.info("增加用户余额成功: userId={}, amount={}, beforeBalance={}, afterBalance={}", 
                userId, amount, beforeBalance, afterBalance);
        
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deductUserBalance(Long userId, BigDecimal amount, Integer type, String orderNo, 
                                    String title, String description) {
        // 查询用户当前余额
        YunkeUser user = userMapper.selectById(userId);
        if (user == null) {
            throw new YunkeException(YunkeResultCode.USER_NOT_EXIST);
        }
        
        BigDecimal beforeBalance = user.getBalance() != null ? user.getBalance() : BigDecimal.ZERO;
        
        // 验证余额是否足够
        if (beforeBalance.compareTo(amount) < 0) {
            throw new YunkeException(YunkeResultCode.PARAM_ERROR, "余额不足");
        }
        
        BigDecimal afterBalance = beforeBalance.subtract(amount);
        
        // 更新用户余额
        user.setBalance(afterBalance);
        userMapper.updateById(user);
        
        // 记录资金流水（负数表示支出）
        YunkeAmountLog amountLog = new YunkeAmountLog();
        amountLog.setUserId(userId);
        amountLog.setOrderNo(orderNo);
        amountLog.setType(type);
        amountLog.setAmount(amount.negate()); // 负数表示支出
        amountLog.setBeforeBalance(beforeBalance);
        amountLog.setAfterBalance(afterBalance);
        amountLog.setTitle(title);
        amountLog.setDescription(description);
        amountLog.setOperatorId(userId);
        amountLog.setOperatorType(1); // 用户操作
        
        amountLogMapper.insert(amountLog);
        
        log.info("扣减用户余额成功: userId={}, amount={}, beforeBalance={}, afterBalance={}", 
                userId, amount, beforeBalance, afterBalance);
        
        return true;
    }

    /**
     * 生成订单号
     */
    private String generateOrderNo() {
        return "R" + System.currentTimeMillis() + String.valueOf((int)(Math.random() * 1000));
    }

    /**
     * 生成提现单号
     */
    private String generateWithdrawalNo() {
        return "W" + System.currentTimeMillis() + String.valueOf((int)(Math.random() * 1000));
    }

    /**
     * 计算冻结金额（待审核的提现金额）
     */
    private BigDecimal calculateFrozenAmount(Long userId) {
        List<YunkeWithdrawal> pendingWithdrawals = withdrawalMapper.selectList(
            new LambdaQueryWrapper<YunkeWithdrawal>()
                .eq(YunkeWithdrawal::getUserId, userId)
                .eq(YunkeWithdrawal::getAuditStatus, 0) // 待审核
        );
        
        return pendingWithdrawals.stream()
            .map(YunkeWithdrawal::getAmount)
            .reduce(BigDecimal.ZERO, BigDecimal::add);
    }
} 